#ifndef __CAPAINDICES_CONEXIONCAPMETADATA_CPP
#define __CAPAINDICES_CONEXIONCAPMETADATA_CPP

/*****************************************************************************
*                     Organizacion de Datos - 75.06                          *
*                         Catedra Lic. Servetto                              *
*            Facultad de Ingenieria - Universidad de Buenos Aires            *
******************************************************************************/ 

#include "../Comun/ConversorDeStreams.h"
#include "ConexionCapaMetadata.h"

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

using namespace std;
using namespace Comun;

namespace CapaConsulta
{

	static int contadorOperaciones = 0;

	void ConexionCapaMetadata::GenerarLlamada(stringstream* entrada, stringstream* salida)
	{
		if (contadorOperaciones < 0)
			contadorOperaciones = 0;

		stringstream* s = new stringstream();
		*s << "Transacciones/CapaMetadata/Entrada/" << contadorOperaciones << ".txt";

		ofstream archivoEntrada(s->str().c_str());
		archivoEntrada << salida->rdbuf();
		archivoEntrada.close();

#ifdef WIN32

		s = new stringstream();
		*s << "CapaMetadata.EXE " << contadorOperaciones;

		system(s->str().c_str());

#else

		s = new stringstream();
		*s << "./CapaMetadata " << contadorOperaciones;

		system(s->str().c_str());

#endif

		s = new stringstream();
		*s << "Transacciones/CapaMetadata/Salida/" << contadorOperaciones << ".txt";

		ifstream* archivoSalida = new ifstream();
		
		archivoSalida->open(s->str().c_str());

		(*entrada) << archivoSalida->rdbuf();

		archivoSalida->close();
		delete archivoSalida;

		contadorOperaciones++;
	};

	bool ConexionCapaMetadata::ExisteClase(string clase, Clase **instancia){

		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::ClasePresente, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		bool resultado = ConversorDeStreams::StreamABooleano(entrada);
		if (resultado)
			*instancia = ConversorDeStreams::StreamAClase(entrada);
		else
			*instancia = NULL;		

		return resultado;
	};

	Resultado* ConexionCapaMetadata::InsertarInstancia(Clase *clase, list<ClaveValor> *datos){

		Resultado* res = new Resultado();
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::InsertarInstancia, salida );
		ConversorDeStreams::CadenaAStream( *clase->NombreClase, salida );
		ConversorDeStreams::ListaDatosAStream(datos,salida);

		GenerarLlamada(entrada, salida);

		res->Codigo = (CodigoConsultaResultado) ConversorDeStreams::StreamAEntero(entrada);		
		getline(*entrada,(* res->Mensaje));
		getline(*entrada,(* res->Mensaje));
		return res;
	};

	Resultado* ConexionCapaMetadata::BorrarInstancia(Clase *clase, CondicionCompuesta *condiciones)
	{
		Resultado* res = new Resultado();
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::BorrarInstancia, salida );
		ConversorDeStreams::CadenaAStream( *clase->NombreClase, salida );
		ConversorDeStreams::CondicionAStream(condiciones,salida);

		GenerarLlamada(entrada, salida);

		res->Codigo = (CodigoConsultaResultado) ConversorDeStreams::StreamAEntero(entrada);		
		getline(*entrada,(* res->Mensaje));
		getline(*entrada,(* res->Mensaje));
		return res;
	}
	
	Resultado* ConexionCapaMetadata::ActualizarInstancia(Clase *clase, list<ClaveValor> *datos, CondicionCompuesta *condiciones)
	{
		Resultado* res = new Resultado();
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::ActualizarInstancia, salida );
		ConversorDeStreams::CadenaAStream( *clase->NombreClase, salida );
		ConversorDeStreams::ListaDatosAStream(datos,salida);
		ConversorDeStreams::CondicionAStream(condiciones,salida);

		GenerarLlamada(entrada, salida);

		res->Codigo = (CodigoConsultaResultado) ConversorDeStreams::StreamAEntero(entrada);		
		getline(*entrada,(* res->Mensaje));
		getline(*entrada,(* res->Mensaje));
		return res;
	}

	Resultado* ConexionCapaMetadata::SeleccionarInstancia(Clase *clase, list<string>* miembros, CondicionCompuesta *condiciones)
	{
		Resultado* res = new Resultado();
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::SeleccionarInstancia, salida );
		ConversorDeStreams::CadenaAStream( *clase->NombreClase, salida );
		ConversorDeStreams::ListaMiembrosAStream(miembros,salida);
		ConversorDeStreams::CondicionAStream(condiciones,salida);

		GenerarLlamada(entrada, salida);

		res->Codigo = (CodigoConsultaResultado) ConversorDeStreams::StreamAEntero(entrada);		
		getline(*entrada,(* res->Mensaje));
		getline(*entrada,(* res->Mensaje));
		
		delete res->ArchivoResultado;
		res->ArchivoResultado = new string(ConversorDeStreams::StreamACadena(entrada));

		return res;
	}

	Resultado* ConexionCapaMetadata::CrearClase(string *path)
	{
		Resultado* resultado = new Resultado();
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::CrearClase, salida );
		ConversorDeStreams::CadenaAStream( *path, salida );

		GenerarLlamada(entrada, salida);

		bool r = ConversorDeStreams::StreamABooleano(entrada);		
		if (r)
			resultado->Codigo = ExitoConsulta;
		else
			resultado->Codigo = ErrorConsulta;

		getline(*entrada,(* resultado->Mensaje));
		getline(*entrada,(* resultado->Mensaje));
		return resultado;
	}
	
}

#endif
